var util = require('../utils/util.js');
var models = util.models;
var DAO = {};
var isArray,isString,isObject;

/**
 * DAO代理，负责注入models对象
 * @param handler models接收方法
 * @param onError 出错回调方法
 */
DAO.proxy = function (handler,onError){
    var err = null;
    if (!models) {
        models = util.models;
        !models && onError(util.getDbError());
    }
    if(models){
        handler(models);
    }
}

/**
 * 校验参数
 * @param expect 校验规则
 * @param actual 待校验参数
 * @returns {{result: Object}}
 */
DAO.validate = function (expect,actual){
    var result = {valid:false};
    var error = {code:'400',msg:''};
    if(!isArray(expect) && !isString(expect)) {
        error.msg = '参数类型有误';
        result.error = error;
        return result;
    }
    if(!actual) actual = {};
    var errMsg = paramsWithOrCheck(expect,actual);
    if(errMsg){
        error.msg = errMsg;
        result.error = error;
    }else{
       result.valid = true;
    }
    return result;
}

/**
 * 根据指定属性获取参数对象
 * @param expect 期待获取的属性
 * @param actual 带值的原始参数对象
 * @returns {{result: Object}}
 */
DAO.getParams = function(expect,actual){
    var result = {};
    var has = {},not=[];
    if(isString(expect)) expect = [expect];
    expect.forEach(function (attr) {
        if(attrNotExist(attr,actual)){
            not.push(attr);
        }else{
            has[attr] = actual[attr];
        }
    });
    result.has = has;
    result.not = not;
    return result;
}

/**
 * 必填项验证
 */
function checkParams(checkRuleArray, params) {
    var errorAttrIndex = -1;
    for (var i = 0; i < checkRuleArray.length; i++) {
        if (attrNotExist(checkRuleArray[i],params)) {
            errorAttrIndex = i;
            break;
        }
    }
    if (errorAttrIndex != -1) {
        return "缺少" + checkRuleArray[errorAttrIndex] + "参数";
    } else {
        return false;
    }
}

/**
 * 必填/选填项验证,选填项用'|'分隔
 * 如checkRule=['name|email|mobile','password'] 或 checkRule='password'
 **/
function paramsWithOrCheck(checkRule,params){
    if(checkRule==null || checkRule==undefined) return false;
    if(isString(checkRule)) checkRule = [checkRule];
    if(!isArray(checkRule)) return '校验规则不合法';
    var requires = [];//必填校验项
    var selectable = [];//N选1校验项
    checkRule.forEach(function (ruleDesc) {
        if(isString(ruleDesc)){
           var rules = ruleDesc.split('|');
           var realRules=[];
           rules.forEach(function (rule) {
               var realRule = trim(rule);
               if(realRule.length>0){
                   realRules.push(realRule);
               }
           });
           if(realRules.length==1){//必须
               requires.push(realRules[0]);
           }else if(realRules.length>1){//N选1
               selectable.push(realRules);
           }
        }
    });
    var error = null;
    if(requires.length>0){//校验必填项
        error = checkParams(requires, params);
        if(error) return error;
    }
    if(selectable.length>0){//校验选填项
       selectable.forEach(function (orCheckArray) {
           if(error) return true;
           for(var i=0;i<orCheckArray.length;i++){
               if(!attrNotExist(orCheckArray[i],params)) break;
               if(i==orCheckArray.length-1){
                  error = '参数不合法：['+orCheckArray.join()+']'+orCheckArray.length+'选1';
               }
           }
       });
       if(error) return error;
    }
    return false;
}

DAO.isObject = isObject = function (o){
   return !isArray(o) && typeof o === 'object';
}

DAO.isArray = isArray = function (o){
    return Object.prototype.toString.call(o)=='[object Array]';
}

DAO.isString = isString = function isString(o){
    return typeof o == 'string';
}

function isAbsoluteEmpty(o){
    return o === undefined || o === null;
}

function attrNotExist(attr,obj){
    if(!attr || !obj) return true;
    return isAbsoluteEmpty(obj[attr]);
}

function trim(s) {
    s = s?s:'';
    return s.replace(/^\s+|\s+$/gm,'');
}

module.exports = DAO;
